Chcesz ulepszyć ten post? Podaj szczegółowe odpowiedzi na to pytanie, w tym cytaty i wyjaśnij, dlaczego Twoja odpowiedź jest prawidłowa. Odpowiedzi, które nie są wystarczająco szczegółowe, można edytować lub usuwać. Pomyłkowo dodałem pliki do Gita za pomocą polecenia: git dodaj myfile.txt Nie uruchomiłem jeszcze git commit. Czy istnieje sposób na cofnięcie tego, aby te pliki nie zostały uwzględnione w zatwierdzeniu?
2020-12-07 21:21:55
1 2 Kolejny Możesz cofnąć polecenie git add przed zatwierdzeniem za pomocą git resetco spowoduje usunięcie go z bieżącego indeksu (listy, która ma zostać zatwierdzona) bez zmiany czegokolwiek innego. Możesz użyć reset git bez nazwy pliku, aby cofnąć wszystkie należne zmiany. Może się to przydać, gdy jest zbyt wiele plików, aby wyświetlić je jeden po drugim w rozsądnym czasie. W starszych wersjach Gita powyższe polecenia są równoważne odpowiednio git reset HEAD i git reset HEAD i nie powiedzie się, jeśli HEAD jest niezdefiniowane (ponieważ nie wykonałeś jeszcze żadnych zatwierdzeń w repozytorium) lub niejednoznaczne (ponieważ stworzył gałąź o nazwie HEAD, co jest głupią rzeczą, której nie powinieneś robić). Zostało to zmienione w Git 1.8.2, więc w nowoczesnych wersjach Gita możesz użyć powyższych poleceń nawet przed dokonaniem pierwszego zatwierdzenia: „git reset” (bez opcji i parametrów) używane do wyświetlania błędu, kiedy nie masz żadnych zatwierdzeń w swojej historii, ale teraz to daje pusty indeks (aby dopasować nieistniejące zatwierdzenie, którego nawet nie jesteś). Dokumentacja: reset git | Chcesz: git rm --cached Rozumowanie: Kiedy byłem w tym nowy, po raz pierwszy spróbowałem reset git. (aby cofnąć całe moje początkowe dodanie), tylko po to, aby otrzymać tę (niezbyt) pomocną wiadomość: fatalny: nie udało się rozstrzygnąć „HEAD” jako prawidłowego odniesienia. Okazuje się, że dzieje się tak, ponieważ ref HEAD (gałąź?) Nie istnieje aż do pierwszego zatwierdzenia. Oznacza to, że napotkasz ten sam problem początkującego co ja, jeśli Twój przepływ pracy, podobnie jak mój, wyglądał mniej więcej tak: cd do mojego wspaniałego katalogu nowego projektu, aby wypróbować Git, nową popularność git init git add. status git ... wiele bzdurnych zwojów ... => Cholera, nie chciałem tego wszystkiego dodawać. google „cofnij git add” => znajdź przepełnienie stosu - yay reset git. => fatal: nie udało się rozpoznać „HEAD” jako prawidłowego odniesienia. Okazuje się ponadto, że na liście mailingowej zarejestrowano błąd, który nie jest przydatny. I że poprawne rozwiązanie było właśnie tam na wyjściu stanu Gita (co, tak, przemilczałem jako `` bzdury) ... # Zmiany do zatwierdzenia: # (użyj „git rm --cached ...”, aby usunąć ze sceny) ... Rozwiązaniem rzeczywiście jest użycie git rm --cached PLIK. Zwróć uwagę na ostrzeżenia w innym miejscu - git rm usuwa lokalną kopię roboczą pliku, ale nie, jeśli używasz --cached. Oto wynik działania git help rm: - buforowany Użyj tej opcji, aby usunąć ze sceny i usunąć ścieżki tylko z indeksu. Pliki drzew roboczych, zmodyfikowane lub nie, zostaną pozostawione. Idę do użycia git rm --cached. usunąć wszystko i zacząć od nowa. Jednak nie zadziałało, ponieważ podczas dodawania. jest rekurencyjny, okazuje się, że rm potrzebuje -r do rekurencji. Westchnienie. git rm -r --cached. Okej, teraz wróciłem do punktu wyjścia. Następnym razem użyję -n, aby wykonać próbę i zobaczyć, co zostanie dodane: git dodaj -n. Zapakowałem wszystko w bezpieczne miejsce, zanim zaufałem git help rm o tym, że --cached niczego nie niszczy (a co, jeśli błędnie to wpisałem). | Jeśli wpiszesz: status git Git powie ci, co jest przygotowywane itp., W tym instrukcje, jak to zrobić: użyj "git reset HEAD ...", aby usunąć ze sceny Uważam, że Git całkiem nieźle namawia mnie do zrobienia właściwej rzeczy w takich sytuacjach. Uwaga: ostatnie wersje Git (1.8.4.x) zmieniły ten komunikat: (użyj "git rm --cached ...", aby usunąć ze sceny) | Aby wyjaśnić: git add przenosi zmiany z bieżącego katalogu roboczego do obszaru przejściowego (indeksu). Ten proces nazywa się etapowaniem. Więc najbardziej naturalnym poleceniem do umieszczenia zmian (zmienionych plików) jest oczywiste: etap git git add to po prostu łatwiejszy do wpisania alias dla etapu git Szkoda, że nie ma poleceń git unstage ani git unadd. Właściwy jest trudniejszy do odgadnięcia lub zapamiętania, ale jest dość oczywisty: git reset HEAD - Możemy łatwo stworzyć alias do tego: git config --global alias.unadd 'reset HEAD -' git config --global alias.unstage 'reset HEAD -' Na koniec mamy nowe polecenia: git dodaj plik1 git stage plik 2 git unadd plik2 git unstage plik1 Osobiście używam jeszcze krótszych aliasów: git a # Do przemieszczania git u # Do unstagingu | Dodatkowo do zaakceptowanej odpowiedzi, jeśli błędnie dodany plik był ogromny, prawdopodobnie zauważysz, że nawet po usunięciu go z indeksu za pomocą polecenia „git reset” nadal wydaje się zajmować miejsce w katalogu .git. Nie ma się czym martwić; plik faktycznie nadal znajduje się w repozytorium, ale tylko jako „luźny obiekt”. Nie zostanie skopiowany do innych repozytoriów (przez klonowanie, wypychanie), a przestrzeń zostanie ostatecznie odzyskana - choć może nie nastąpi to wkrótce. Jeśli jesteś niespokojny, możesz biegać: git gc --prune = teraz Aktualizacja (poniżej jest moja próba wyjaśnienia pewnych nieporozumień, które mogą wynikać z odpowiedzi, które są najbardziej przychylne): Więc co jest prawdziwym cofnięciem git add? git reset HEAD ? lub git rm --cached ? Ściśle mówiąc, i jeśli się nie mylę: żadnych. git add nie może zostać cofnięty - ogólnie bezpiecznie. Przypomnijmy sobie najpierw, co faktycznie robi git add : Jeśli nie był wcześniej śledzony, git add dodaje go dopamięć podręczna z jej aktualną zawartością. Jeśli był już śledzony, git add zapisuje bieżącą zawartość (migawkę, wersję) do pamięci podręcznej. W Git ta akcja jest nadal nazywana dodawaniem (a nie zwykłą aktualizacją), ponieważ dwie różne wersje (migawki) pliku są traktowane jako dwa różne elementy: dlatego rzeczywiście dodajemy nowy element do pamięci podręcznej, aby ostatecznie zostać popełnione później. W związku z tym pytanie jest nieco niejednoznaczne: Pomyłkowo dodałem pliki za pomocą polecenia ... Scenariusz OP wydaje się być pierwszym (nieśledzony plik), chcemy "cofnąć", aby usunąć plik (nie tylko bieżącą zawartość) ze śledzonych elementów. W takim przypadku można uruchomić git rm --cached . Moglibyśmy również uruchomić git reset HEAD . Jest to ogólnie preferowane rozwiązanie, ponieważ działa w obu scenariuszach: powoduje również cofnięcie, gdy błędnie dodaliśmy wersję już śledzonego elementu. Ale są dwa zastrzeżenia. Po pierwsze: jest (jak wskazano w odpowiedzi) tylko jeden scenariusz, w którym git reset HEAD nie działa, ale git rm --cached działa: nowe repozytorium (bez zatwierdzeń). Ale tak naprawdę jest to praktycznie nieistotny przypadek. Po drugie: pamiętaj, że git reset HEAD nie może w magiczny sposób odzyskać zawartości wcześniej zbuforowanego pliku, po prostu ponownie zsynchronizuje go z HEAD. Jeśli nasz błędny dodatek git nadpisał poprzednią niezatwierdzoną wersję, nie możemy jej odzyskać. Dlatego ściśle mówiąc nie możemy cofnąć [*]. Przykład: $ git init $ echo "wersja 1"> plik.txt $ git add file.txt # Najpierw dodaj plik.txt $ git commit -m 'first commit' $ echo "wersja 2"> plik.txt $ git add file.txt # Stage (nie zatwierdzaj) „wersja 2” pliku file.txt $ git diff --cached plik.txt -wersja 1 + wersja 2 $ echo "wersja 3"> plik.txt $ git diff plik.txt -wersja 2 + wersja 3 $ git add file.txt # Ups, nie mieliśmy tego na myśli $ git reset HEAD file.txt # Cofnąć? $ git diff --cached file.txt # Oczywiście nie ma różnicy. stage == HEAD $ git diff file.txt # Nieodwracalnie utraciliśmy "wersję 2" -wersja 1 + wersja 3 Oczywiście nie jest to bardzo krytyczne, jeśli po prostu postępujemy zgodnie ze zwykłym leniwym przepływem pracy, robiąc „git add” tylko w celu dodania nowych plików (przypadek 1) i aktualizujemy nową zawartość za pomocą polecenia commit, git commit -a. * (Edytuj: powyższe jest praktycznie poprawne, ale nadal mogą istnieć pewne nieco hakerskie / zawiłe sposoby odzyskiwania zmian, które zostały zainscenizowane, ale nie zostały zatwierdzone, a następnie nadpisane - patrz komentarze Johannesa Matokica i iolsmit) | Cofnięcie pliku, który został już dodany, jest dość łatwe dzięki Git. Aby zresetować plik myfile.txt, który został już dodany, użyj: git reset HEAD myfile.txt Wyjaśnienie: Po przygotowaniu niechcianych plików, aby cofnąć, możesz wykonać reset git. Head jest nagłówkiem twojego pliku w lokalnym, a ostatnim parametrem jest nazwa twojego pliku. Utworzyłem dla Ciebie kroki na poniższym obrazku, w tym wszystkie kroki, które mogą się zdarzyć w takich przypadkach: | git rm --cached. -r rekurencyjnie „cofnie” wszystko, co dodałeś z bieżącego katalogu | Biegać git gui i usuń wszystkie pliki ręcznie lub zaznaczając je wszystkie i klikając przycisk unstage from commit. | Pytanie nie jest jasno postawione. Powodem jest to, że git add ma dwa znaczenia: dodanie nowego pliku do obszaru przemieszczania, a następnie cofnij za pomocą git rm --cached file. dodanie zmodyfikowanego pliku do obszaru przemieszczania, a następnie cofnij za pomocą git reset HEAD file. W razie wątpliwości użyj git reset pliku HEAD Ponieważ w obu przypadkach działa zgodnie z oczekiwaniami. Ostrzeżenie: jeśli wykonasz polecenie git rm --cached plik na pliku, który został zmodyfikowany (plik, który istniał wcześniej w repozytorium), plik zostanie usunięty po zatwierdzeniu git! Będzie on nadal istniał w twoim systemie plików, ale jeśli ktoś inny wyciągnie twoje zatwierdzenie, plik zostanie usunięty z jego drzewa roboczego. Status git powie ci, czy plik był nowym plikiem czy zmodyfikowanym: Na gałęzi master Zmiany do zatwierdzenia: (użyj "git reset HEAD ...", aby usunąć ze sceny) nowy plik: my_new_file.txt zmodyfikowany: my_modified_file.txt | Git ma polecenia dla każdej możliwej do wyobrażenia czynności, ale potrzebuje rozległej wiedzy, aby wszystko naprawić, i dlatego jest w najlepszym przypadku sprzeczny z intuicją ... Co robiłeś wcześniej: Zmieniono plik i użyto git add. Lub git add . Czego chcesz: Usuń plik z indeksu, ale zachowaj jego wersję i pozostaw z niezatwierdzonymi zmianami w kopii roboczej: git reset HEAD Zresetuj plik do ostatniego stanu z HEAD, cofając zmiany i usuwając je z indeksu: # Pomyśl `svn revert ` IIRC. git reset HEAD git checkout # Jeśli masz ` ` o nazwie takiej jak ` `, użyj: git checkout - Jest to potrzebne, ponieważ reset git --hard HEAD nie będzie działać z pojedynczymi plikami. Usuń z indeksu i wersjonowania, zachowując niewersjonowany plik ze zmianami w kopii roboczej: git rm --cached Całkowicie usuń plik z kopii roboczej i wersjonowania: git rm | Jeśli jesteś na swoim początkowym zatwierdzeniu i nie możesz użyć gitreset, po prostu zadeklaruj „bankructwo Git”, usuń folder .git i zacznij od nowa | Podobnie jak w przypadku wielu innych odpowiedzi, możesz użyć resetowania git ALE: Znalazłem ten świetny mały post, który faktycznie dodaje polecenie Git (cóż, alias) dla git unadd: zobacz git unadd po szczegóły lub ... Po prostu, git config --global alias.unadd "reset HEAD" Teraz możesz git unadd foo.txt bar.txt | Użyj git add -i, aby usunąć właśnie dodane pliki z nadchodzącego zatwierdzenia. Przykład: Dodawanie niepotrzebnego pliku: $ git dodaj foo Stan $ git # Na gałęzi master # Zmiany do zatwierdzenia: # (użyj "git reset HEAD ...", aby usunąć ze sceny) # # nowy plik: foo # # Nieśledzone pliki: # (użyj „git add ...”, aby uwzględnić to, co zostanie zatwierdzone) # [...] # Przechodzenie do interaktywnego dodawania, aby cofnąć dodawanie (polecenia wpisywane tutaj na git to „r” (przywróć), „1” (pierwszy wpis na liście pokazuje przywrócenie), „powrót”, aby wyjść z trybu przywracania i „q” (porzucić): $ git add -i inscenizowana ścieżka niestacjonarna 1: + 1 / -0 nic foo *** Polecenia *** 1: [s] tatus 2: [u] pdate 3: [r] evert 4: [a] dd untracked 5: [p] atch 6: [d] iff 7: [q] uit 8: [h] elp Co teraz> r inscenizowana ścieżka niestacjonarna 1: + 1 / -0 nic [f] oo Przywróć >> 1 inscenizowana ścieżka niestacjonarna * 1: + 1 / -0 nic [f] oo Przywróć >> uwaga: foo nie jest teraz śledzone. odwrócił jedną ścieżkę *** Polecenia *** 1: [s] tatus 2: [u] pdate 3: [r] evert 4: [a] dd nieśledzony 5: [p] atch 6: [d] iff 7: [q] uit 8: [h] elp Co teraz> q PA. $ Otóż to! Oto twój dowód na to, że „foo” wrócił na nieśledzoną listę: Stan $ git # Na gałęzi master # Nieśledzone pliki: # (użyj „git add ...”, aby uwzględnić to, co zostanie zatwierdzone) # [...] # bla nic nie zostało dodane do zatwierdzenia, ale obecne są nieśledzone pliki (użyj „git add” do śledzenia) $ | Można do tego użyć git remove lub git rm, z flagą --cached. Próbować: git help rm | Oto sposób na uniknięcie tego irytującego problemu podczas rozpoczynania nowego projektu: Utwórz katalog główny dla swojego nowego projektu. Uruchom git init. Teraz utwórz plik .gitignore (nawet jeśli jest pusty). Zatwierdź swój plik .gitignore. Git bardzo utrudnia resetowanie git, jeśli nie masz żadnych zatwierdzeń. Jeśli utworzysz małe wstępne zatwierdzenie tylko po to, aby je mieć, możesz potem git add -A i git resetować tyle razy, ile chcesz, aby wszystko było dobrze. Kolejną zaletą tej metody jest to, że jeśli później napotkasz problemy z zakończeniem linii i będziesz musiał odświeżyć wszystkie pliki, jest to łatwe: Sprawdź to wstępne zatwierdzenie. Spowoduje to usunięcie wszystkich plików. Następnie sprawdź ponownie swoje ostatnie zatwierdzenie. Spowoduje to pobranie nowych kopii plików przy użyciu bieżących ustawień końca wiersza. | Być może Git ewoluował, odkąd opublikowałeś swoje pytanie. $> git --version git w wersji 1.6.2.1 Teraz możesz spróbować: git reset HEAD. To powinno być to, czego szukasz. | Zwróć uwagę, że jeśli nie określisz wersji, musisz dołączyć separator. Przykład z mojej konsoli: git reset fatal: niejednoznaczny argument '<ścieżka_do_pliku>': nieznana wersja lub ścieżka nie znajduje się w drzewie roboczym. Użyj znaku „-”, aby oddzielić ścieżki od wersji git reset - <ścieżka_do_pliku> Niestandardowe zmiany po resecie: M <ścieżka_do_pliku> (Git w wersji 1.7.5.4) | Aby usunąć nowe pliki z obszaru przemieszczania (i tylko w przypadku nowego pliku), jak zasugerowano powyżej: git rm --cached PLIK Użyj rm --cached tylko dla nowych plików dodanych przypadkowo. | Aby zresetować każdy plik w określonym folderze (i jego podfolderach), możesz użyć następującego polecenia: reset git * | Użyj polecenia *, aby obsługiwać wiele plików naraz: git reset HEAD * .prj git reset HEAD * .bmp git reset HEAD * gdb * itp. | Po prostu wpisz git reset, nastąpi powrót i wygląda to tak, jakbyś nigdy nie wpisał git add. od twojego ostatniego zatwierdzenia. Upewnij się, że zobowiązałeś się wcześniej. | Załóżmy, że tworzę nowy plik, newFile.txt: Załóżmy, że przypadkowo dodam plik, git dodaj nowy plik.txt: Teraz chcę cofnąć to dodawanie, przed zatwierdzeniem, git reset newFile.txt: | W przypadku konkretnego pliku: git reset my_file.txt git checkout moj_plik.txt Dla wszystkich dodanych plików: reset git. git checkout. Uwaga: wyewidencjonowanie zmienia kod w plikach i przechodzi do ostatniego zaktualizowanego (zatwierdzonego) stanu. reset nie zmienia kodów; po prostu resetuje nagłówek. | Aby cofnąć dodawanie git, użyj: git reset nazwa pliku | To polecenie usunie twoje zmiany: git reset HEAD nazwa_pliku.txt Możesz także użyć git add -p aby dodać części plików. | Istnieje również tryb interaktywny: git dodaj -i Wybierz opcję 3, aby cofnąć dodawanie plików. W moim przypadku często chcę dodać więcej niż jeden plik, aw trybie interaktywnym możesz użyć takich liczb, aby dodać pliki. To zajmie wszystko oprócz 4: 1, 2, 3 i 5 Aby wybrać sekwencję, po prostu wpisz 1-5, aby wziąć wszystkie od 1 do 5. Pliki przejściowe Git | git add myfile.txt # Spowoduje to dodanie twojego pliku do listy do zatwierdzenia Wręcz przeciwnie do tego polecenia, git reset HEAD myfile.txt # To cofnieto. więc będziesz w poprzednim stanie. Określony będzie ponownie na liście nieśledzonej (poprzedni stan). Zresetuje twoją głowę tym określonym plikiem. więc jeśli twoja głowa tego nie ma, oznacza to, że po prostu ją zresetuje. | git reset nazwa_pliku.txt Usuwa plik o nazwie nazwa_pliku.txt z bieżącego indeksu, obszaru „wkrótce zostanie zatwierdzone”, bez zmiany niczego innego. | git reset nazwa_pliku.txt Usuwa plik o nazwie nazwa_pliku.txt z bieżącego indeksu, obszaru „wkrótce zostanie zatwierdzone”, bez zmiany niczego innego. | W Sourcetree możesz to łatwo zrobić za pomocą GUI. Możesz sprawdzić, którego polecenia Sourcetree używa do usunięcia z poczekalni pliku. Utworzyłem nowy plik i dodałem go do Gita. Następnie zdemontowałem to za pomocą GUI Sourcetree. Oto wynik: Usuwanie plików z poczekalni [08/12/15 10:43] git -c diff.mnemonicprefix = false -c core.quotepath = false -c credential.helper = sourcetree reset -q - path / to / file / filename.java Sourcetree używa resetowania do usuwania ze sceny nowych plików. | 1 2 Kolejny Bardzo aktywne pytanie. Zdobądź 10 punktów reputacji, aby odpowiedzieć na to pytanie. Wymóg dotyczący reputacji pomaga chronić to pytanie przed spamem i brakiem odpowiedzi. Nie szukasz odpowiedzi? Przeglądaj inne pytania oznaczone tagiem git kontrola wersji git-commit git-stage lub zadaj własne pytanie.